﻿using System;
using System.IO;
using System.Linq;
using System.Web;
using ExifLibrary;
using GeoFramework;
using LetsDoIt.Logging;

namespace LetsDoItWS.BO
{
    /// <summary>
    /// factory used for image storage
    /// </summary>
    public static class ImageStorageFactory
    {
        /// <summary>
        /// Save image to disk
        /// </summary>
        /// <param name="wasteId">trash point ID</param>
        /// <param name="userId">user ID</param>
        /// <param name="imageContent">jpeg image content as byte array</param>
        /// <param name="tp">trash point info</param>
        /// <returns>true if succesful</returns>
        public static bool SaveImage(string wasteId, string userId, byte[] imageContent, TrashPoint tp)
        {
            try
            {
                string imagesFolder = System.Configuration.ConfigurationManager.AppSettings["ImagesFolder"];
                string wsImagePrefix = System.Configuration.ConfigurationManager.AppSettings["WsImagePrefix"];
                imagesFolder = Path.Combine(HttpContext.Current.Request.MapPath("~"), imagesFolder);
                if (!Directory.Exists(imagesFolder))
                    Directory.CreateDirectory(imagesFolder);
                int imageCount = 0;
                string fileName;
                string fileNameOnly = Path.Combine(imagesFolder, string.Format("{0}_{1}_{2}.jpg", wasteId, userId, imageCount));
                while (File.Exists(Path.Combine(imagesFolder, fileNameOnly)))
                {
                    imageCount++;
                    fileNameOnly = string.Format("{0}_{1}_{2}.jpg", wasteId, userId, imageCount);
                }
                fileName = Path.Combine(imagesFolder, fileNameOnly);

                using (FileStream fs = File.Create(fileName))
                {
                    fs.Write(imageContent, 0, imageContent.Length);
                    fs.Flush();
                }
                //
                //update geolocation
                try
                {
                    ExifFile file = ExifFile.Read(fileName);
					
                    //latitude + longitude 
                    GeoFramework.Latitude latitude = new Latitude((double)tp.latitude_TPT);
                    GeoFramework.Longitude longitude = new Longitude((double)tp.longitude_TPT);

                    file.Properties[ExifTag.GPSLatitude] = new GPSLatitudeLongitude(ExifTag.GPSLatitude, latitude.Hours, latitude.Minutes, (float)latitude.Seconds);
                    file.Properties[ExifTag.GPSLatitudeRef] = new ExifEnumProperty<GPSLatitudeRef>(ExifTag.GPSLatitudeRef, latitude.Hemisphere == LatitudeHemisphere.South ? GPSLatitudeRef.South : GPSLatitudeRef.North);
                    file.Properties[ExifTag.GPSLongitude] = new GPSLatitudeLongitude(ExifTag.GPSLongitude, longitude.Hours, longitude.Minutes, (float)longitude.Seconds); 
                    file.Properties[ExifTag.GPSLongitudeRef] = new ExifEnumProperty<GPSLongitudeRef>(ExifTag.GPSLongitudeRef, longitude.Hemisphere == LongitudeHemisphere.West ? GPSLongitudeRef.West :  GPSLongitudeRef.East);

                    //LDIR copyright
                    ExifAscii copyright = new ExifAscii(ExifTag.Copyright, "LDIR");
                    file.Properties.Add(copyright);

                    //description
                    ExifAscii description = new ExifAscii(ExifTag.ImageDescription, tp.description_TPT);
                    file.Properties.Add(description);

                    //author
                    User userInfo;
                    using (ldirdbEntities dataContext = new ldirdbEntities())
                    {
                        userInfo = dataContext.Users.FirstOrDefault(u => u.id == tp.user_TPT);
                    }
                    string userName = userInfo != null ? userInfo.name : string.Empty;
                    ExifAscii author = new ExifAscii(ExifTag.WindowsAuthor, userName);
                    file.Properties.Add(author);

                    //comments
                    ExifAscii comment = new ExifAscii(ExifTag.WindowsComment, tp.description_TPT);
                    file.Properties.Add(comment);

                    file.Save(fileName);

                }
                catch (Exception exgeo)
                {
                    LoggerManager.Current.ErrorFormat(typeof(object), "WS Error geotagging : {0}", exgeo);
                }

                //update trashpoint
                using (ldirdbEntities dataContext = new ldirdbEntities())
                {
                    TrashPoint point = dataContext.TrashPoints.FirstOrDefault(t => t.id_TPT == tp.id_TPT);
                    point.photo2_TPT = point.photo1_TPT;
                    fileNameOnly = new FileInfo(fileName).Name;
                    point.photo1_TPT = wsImagePrefix + fileNameOnly;
                    dataContext.SaveChanges(true);
                }

                return true;
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
            }

            return false;
        }


        /// <summary>
        /// Gets fist image URL of a waste point
        /// </summary>
        /// <param name="wasteId">waste point id</param>
        /// <returns>url string</returns>
        public static string GetFirstImageURL(int wasteId)
        {
            string result = string.Empty;
            try
            {
                string imagesFolder = System.Configuration.ConfigurationManager.AppSettings["ImagesFolder"];
                string wsImagePrefix = System.Configuration.ConfigurationManager.AppSettings["WsImagePrefix"];
                string wsImagesUri = System.Configuration.ConfigurationManager.AppSettings["WsImagesUri"];
                string formImagesUri = System.Configuration.ConfigurationManager.AppSettings["FormImagesUri"];
                imagesFolder = Path.Combine(HttpContext.Current.Request.MapPath("~"), imagesFolder);
                imagesFolder = (new DirectoryInfo(imagesFolder)).Name;

                TrashPoint tp;
                using (ldirdbEntities dataContext = new ldirdbEntities())
                {
                    tp = dataContext.TrashPoints.FirstOrDefault(t => t.id_TPT == wasteId);                    
                }
                if (tp != null)
                {
                    if (!string.IsNullOrEmpty(tp.photo1_TPT))
                    {
                        string photoStr = tp.photo1_TPT;
                        photoStr = photoStr.StartsWith(wsImagePrefix) ? photoStr.Substring(wsImagePrefix.Length) : photoStr;
                        photoStr = photoStr.StartsWith("/") || photoStr.StartsWith("\\") ?
                            photoStr.Substring(1) :
                            photoStr;
                        result = (tp.photo1_TPT.StartsWith(wsImagePrefix) ? wsImagesUri + imagesFolder + "\\" : formImagesUri) + photoStr;
                        result = result.Replace("\\", "/");
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
            }
            return result;
        }

        /// <summary>
        /// Gets second image URL of a waste point
        /// </summary>
        /// <param name="wasteId">waste point id</param>
        /// <returns>url string</returns>
        public static string GetSecondImageURL(int wasteId)
        {
            string result = string.Empty;
            try
            {
                string imagesFolder = System.Configuration.ConfigurationManager.AppSettings["ImagesFolder"];
                string wsImagePrefix = System.Configuration.ConfigurationManager.AppSettings["WsImagePrefix"];
                string wsImagesUri = System.Configuration.ConfigurationManager.AppSettings["WsImagesUri"];
                string formImagesUri = System.Configuration.ConfigurationManager.AppSettings["FormImagesUri"];
                imagesFolder = Path.Combine(HttpContext.Current.Request.MapPath("~"), imagesFolder);
                imagesFolder = (new DirectoryInfo(imagesFolder)).Name;

                TrashPoint tp;
                using (ldirdbEntities dataContext = new ldirdbEntities())
                {
                    tp = dataContext.TrashPoints.FirstOrDefault(t => t.id_TPT == wasteId);
                }
                if (tp != null)
                {
                    if (!string.IsNullOrEmpty(tp.photo2_TPT))
                    {
                        string photoStr = tp.photo2_TPT;
                        photoStr = photoStr.StartsWith(wsImagePrefix) ? photoStr.Substring(wsImagePrefix.Length) : photoStr;
                        photoStr = photoStr.StartsWith("/") || photoStr.StartsWith("\\") ?
                            photoStr.Substring(1) :
                            photoStr;
                        result = (tp.photo2_TPT.StartsWith(wsImagePrefix) ? wsImagesUri + imagesFolder + "\\" : formImagesUri) + photoStr;
                        result = result.Replace("\\", "/");
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerManager.Current.ErrorFormat(typeof(object), "WS Error : {0}", ex);
            }
            return result;
        }
    }
}